Ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalarni samarali render qilish usuli - WebGL klasterli yoritish taqsimotini o'rganing. Uning tamoyillari, tatbiq etilishi va ishlash samaradorligini optimallashtirish strategiyalari bilan tanishing.
WebGL Klasterli Yoritish Taqsimoti: Dinamik Yorug'likni Tarqatish
Ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalarni real vaqtda render qilish jiddiy muammoni keltirib chiqaradi. Har bir fragment uchun barcha yorug'lik manbalarini aylanib chiqish kabi sodda yondashuvlar tezda hisoblash jihatdan samarasiz bo'lib qoladi. WebGL Klasterli Yoritish Taqsimoti bu muammoga kuchli va samarali yechim taklif etadi, u ko'rish frustumini klasterlar to'riga bo'lib, yorug'lik manbalarini ularning fazoviy joylashuviga qarab klasterlarga taqsimlaydi. Bu har bir fragment uchun ko'rib chiqilishi kerak bo'lgan yorug'lik manbalari sonini sezilarli darajada kamaytirib, ishlash samaradorligini oshiradi.
Muammoni Tushunish: Dinamik Yoritishning Qiyinchiliklari
An'anaviy to'g'ridan-to'g'ri rendering (forward rendering) yuqori zichlikdagi dinamik yorug'lik manbalari bilan ishlashda kengayish muammolariga duch keladi. Har bir fragment (piksel) uchun shader yoritish hissasini hisoblash uchun barcha yorug'lik manbalarini aylanib chiqishi kerak. Bu murakkablik O(n) bo'lib, bu yerda n - yorug'lik manbalari soni, bu esa yuzlab yoki minglab yorug'lik manbalari bo'lgan sahnalar uchun barqaror emas. Kechiktirilgan rendering (deferred rendering) ushbu muammolarning ba'zilarini hal qilsa-da, o'zining murakkabliklarini keltirib chiqaradi va har doim ham optimal tanlov emas, ayniqsa mobil qurilmalarda yoki G-bufer o'tkazuvchanligi muammo bo'lishi mumkin bo'lgan WebGL muhitlarida.
Klasterli Yoritish Taqsimoti bilan Tanishtirish
Klasterli Yoritish Taqsimoti ham to'g'ridan-to'g'ri, ham kechiktirilgan rendering afzalliklaridan foydalanib, ularning kamchiliklarini yumshatadigan gibrid yondashuvni taklif etadi. Asosiy g'oya 3D sahnani kichik hajmlar yoki klasterlar to'riga bo'lishdir. Har bir klaster o'sha klaster ichidagi piksellarga potentsial ta'sir ko'rsatadigan yorug'lik manbalari ro'yxatini saqlaydi. Rendering paytida, shader faqat joriy fragmentni o'z ichiga olgan klasterga tayinlangan yorug'lik manbalarini aylanib chiqishi kerak, bu esa yorug'lik hisob-kitoblari sonini sezilarli darajada kamaytiradi.
Asosiy Tushunchalar:
- Klasterlar: Bular ko'rish frustumini qismlarga ajratuvchi kichik 3D hajmlardir. Klasterlarning o'lchami va joylashuvi ishlash samaradorligiga sezilarli ta'sir qiladi.
- Yorug'likni Taqsimlash: Ushbu jarayon qaysi yorug'lik manbalari qaysi klasterlarga ta'sir qilishini aniqlaydi. Optimal ishlash uchun samarali taqsimlash algoritmlari juda muhim.
- Shader Optimallashtiruvi: Fragment shaderi taqsimlangan yorug'lik ma'lumotlariga samarali kirishi va ularni qayta ishlashi kerak.
Klasterli Yoritish Taqsimoti Qanday Ishlaydi
Klasterli yoritish taqsimoti jarayonini quyidagi bosqichlarga bo'lish mumkin:
- Klaster Yaratish: Ko'rish frustumi 3D klasterlar to'riga bo'linadi. To'rning o'lchamlari (masalan, X, Y va Z o'qlari bo'yicha klasterlar soni) odatda ekran o'lchamlari va ishlash samaradorligi talablariga qarab tanlanadi. Keng tarqalgan konfiguratsiyalarga 16x9x16 yoki 32x18x32 kiradi, ammo bu raqamlar platforma va kontentga qarab sozlanishi kerak.
- Yorug'lik-Klaster Taqsimoti: Har bir yorug'lik manbai uchun algoritm qaysi klasterlar yorug'likning ta'sir radiusi ichida ekanligini aniqlaydi. Bu yorug'lik manbai pozitsiyasi va har bir klaster markazi orasidagi masofani hisoblashni o'z ichiga oladi. Radius ichidagi klasterlar yorug'likning ta'sir ro'yxatiga, yorug'lik esa klaster yorug'lik ro'yxatiga qo'shiladi. Bu optimallashtirish uchun asosiy soha bo'lib, ko'pincha Bounding Volume Hierarchies (BVH) yoki fazoviy xeshlash kabi usullardan foydalaniladi.
- Ma'lumotlar Tuzilmasini Yaratish: Har bir klaster uchun yorug'lik ro'yxatlari odatda shader tomonidan kirish mumkin bo'lgan bufer obyektida saqlanadi. Bu bufer kirish naqshlarini optimallashtirish uchun turli usullarda tuzilishi mumkin, masalan, yorug'lik indekslarining ixcham ro'yxatidan foydalanish yoki qo'shimcha yorug'lik xususiyatlarini to'g'ridan-to'g'ri klaster ma'lumotlari ichida saqlash.
- Fragment Shaderining Bajarilishi: Fragment shaderi joriy fragment qaysi klasterga tegishli ekanligini aniqlaydi. Keyin u o'sha klaster uchun yorug'lik ro'yxatini aylanib chiqadi va har bir tayinlangan yorug'likdan keladigan yoritish hissasini hisoblaydi.
WebGL'da Amalga Oshirish Tafsilotlari
WebGL'da klasterli yoritish taqsimotini amalga oshirish shader dasturlash va GPU'dagi ma'lumotlarni boshqarishni diqqat bilan ko'rib chiqishni talab qiladi.
1. Klasterlarni Sozlash
Klasterlar to'ri kameraning xususiyatlari (FOV, tomonlar nisbati, yaqin va uzoq tekisliklar) va har bir o'lchamdagi kerakli klasterlar soniga qarab belgilanadi. Klaster hajmini ushbu parametrlarga asoslanib hisoblash mumkin. Odatdagi amalga oshirishda klaster o'lchamlari qat'iy belgilanadi.
const numClustersX = 16;
const numClustersY = 9;
const numClustersZ = 16; //Chuqurlik klasterlari katta sahnalar uchun ayniqsa muhim
// Kamera parametrlari va klasterlar soniga qarab klaster o'lchamlarini hisoblang.
function calculateClusterDimensions(camera, numClustersX, numClustersY, numClustersZ) {
const tanHalfFOV = Math.tan(camera.fov / 2 * Math.PI / 180);
const clusterWidth = 2 * tanHalfFOV * camera.aspectRatio / numClustersX;
const clusterHeight = 2 * tanHalfFOV / numClustersY;
const clusterDepthScale = Math.pow(camera.far / camera.near, 1 / numClustersZ);
return { clusterWidth, clusterHeight, clusterDepthScale };
}
2. Yorug'likni Taqsimlash Algoritmi
Yorug'likni taqsimlash algoritmi har bir yorug'lik manbasini aylanib chiqadi va u qaysi klasterlarga ta'sir qilishini aniqlaydi. Oddiy yondashuv yorug'lik va har bir klaster markazi orasidagi masofani hisoblashni o'z ichiga oladi. Yanada optimallashtirilgan yondashuv esa yorug'likning chegaralovchi sferasini oldindan hisoblaydi. Bu yerdagi hisoblashdagi asosiy to'siq odatda juda ko'p sonli klasterlarni aylanib chiqish zaruratidir. Bu yerda optimallashtirish texnikalari juda muhim. Bu bosqichni CPU'da yoki hisoblash shaderlari (WebGL 2.0+) yordamida bajarish mumkin.
// Yorug'likni taqsimlash uchun psevdo-kod
for (let light of lights) {
for (let x = 0; x < numClustersX; ++x) {
for (let y = 0; y < numClustersY; ++y) {
for (let z = 0; z < numClustersZ; ++z) {
// Klaster markazining dunyo pozitsiyasini hisoblash
const clusterCenter = calculateClusterCenter(x, y, z);
// Yorug'lik va klaster markazi orasidagi masofani hisoblash
const distance = vec3.distance(light.position, clusterCenter);
// Agar masofa yorug'lik radiusida bo'lsa, yorug'likni klasterga qo'shish
if (distance <= light.radius) {
addLightToCluster(light, x, y, z);
}
}
}
}
}
3. Yorug'lik Ro'yxatlari uchun Ma'lumotlar Tuzilmasi
Har bir klaster uchun yorug'lik ro'yxatlari shaderning samarali kirishi uchun qulay formatda saqlanishi kerak. Keng tarqalgan yondashuv WebGL 2.0 da Tekstura Bufer Objekti (TBO) yoki Shader Saqlash Bufer Objekti (SSBO) dan foydalanishdir. TBO yorug'lik indekslarini yoki yorug'lik ma'lumotlarini teksturada saqlaydi, SSBO esa yanada moslashuvchan saqlash va kirish naqshlariga imkon beradi. TBO'lar kengaytmalari orqali WebGL1 ilovalarida keng qo'llab-quvvatlanadi, bu esa kengroq moslikni taklif etadi.
Ikki asosiy yondashuv mavjud:
- Ixcham Yorug'lik Ro'yxati: Faqat har bir klasterga tayinlangan yorug'lik manbalarining indekslarini saqlaydi. Alohida yorug'lik ma'lumotlari buferidan qo'shimcha qidiruvni talab qiladi.
- Klasterdagi Yorug'lik Ma'lumotlari: Yorug'lik xususiyatlarini (pozitsiya, rang, intensivlik) to'g'ridan-to'g'ri klaster ma'lumotlari ichida saqlaydi. Qo'shimcha qidiruvdan qochadi, lekin ko'proq xotira sarflaydi.
// Ixcham yorug'lik ro'yxati bilan Tekstura Bufer Objekti (TBO) dan foydalanish namunasi
// LightIndices: Har bir klasterga tayinlangan yorug'lik indekslari massivi
// LightData: Haqiqiy yorug'lik ma'lumotlarini (pozitsiya, rang va hokazo) o'z ichiga olgan massiv
// Shaderda:
uniform samplerBuffer lightIndices;
uniform samplerBuffer lightData;
uniform ivec3 numClusters;
int clusterIndex = x + y * numClusters.x + z * numClusters.x * numClusters.y;
// Ushbu klasterdagi yorug'lik ro'yxati uchun boshlanish va tugash indeksini olish
int startIndex = texelFetch(lightIndices, clusterIndex * 2).r; //Har bir teksel bitta yorug'lik indeksi va startIndex/endIndex ketma-ket joylashtirilgan deb faraz qilamiz.
int endIndex = texelFetch(lightIndices, clusterIndex * 2 + 1).r;
for (int i = startIndex; i < endIndex; ++i) {
int lightIndex = texelFetch(lightIndices, i).r;
// lightIndex yordamida haqiqiy yorug'lik ma'lumotlarini olish
vec4 lightPosition = texelFetch(lightData, lightIndex * NUM_LIGHT_PROPERTIES).rgba; //NUM_LIGHT_PROPERTIES uniform bo'ladi.
...
}
4. Fragment Shaderini Amalga Oshirish
Fragment shaderi joriy fragment tegishli bo'lgan klasterni aniqlaydi va keyin o'sha klaster uchun yorug'lik ro'yxatini aylanib chiqadi. Shader har bir tayinlangan yorug'likdan keladigan yoritish hissasini hisoblaydi va natijalarni jamlaydi.
// Fragment shaderida
uniform ivec3 numClusters;
uniform vec2 resolution;
// Joriy fragment uchun klaster indeksini hisoblash
ivec3 clusterIndex = ivec3(
int(gl_FragCoord.x / (resolution.x / float(numClusters.x))),
int(gl_FragCoord.y / (resolution.y / float(numClusters.y))),
int(log(gl_FragCoord.z) / log(clusterDepthScale)) //Logarifmik chuqurlik buferini nazarda tutadi.
);
//Klaster indeksi diapazonda qolishini ta'minlash.
clusterIndex = clamp(clusterIndex, ivec3(0), numClusters - ivec3(1));
int linearClusterIndex = clusterIndex.x + clusterIndex.y * numClusters.x + clusterIndex.z * numClusters.x * numClusters.y;
// Klaster uchun yorug'lik ro'yxatini aylanib chiqish
// (Amalga oshirishga qarab TBO yoki SSBO'dan yorug'lik ma'lumotlariga kirish)
// Har bir yorug'lik uchun yoritish hisob-kitoblarini bajarish
Ishlash Samaradorligini Optimallashtirish Strategiyalari
Klasterli yoritish taqsimotining ishlash samaradorligi ko'p jihatdan amalga oshirishning samaradorligiga bog'liq. Ishlashni yaxshilash uchun bir nechta optimallashtirish usullarini qo'llash mumkin:
- Klaster Hajmini Optimallashtirish: Optimal klaster hajmi sahna murakkabligi, yorug'lik zichligi va ekran o'lchamlariga bog'liq. Yorug'likni taqsimlash aniqligi va shader samaradorligi o'rtasidagi eng yaxshi muvozanatni topish uchun turli klaster o'lchamlari bilan tajriba o'tkazish juda muhim.
- Frustum Culling: Frustum culling yorug'likni taqsimlash jarayonidan oldin ko'rish frustumidan butunlay tashqarida bo'lgan yorug'lik manbalarini yo'q qilish uchun ishlatilishi mumkin.
- Yorug'likni Yo'qotish Texnikalari: Yorug'likni yo'qotishni tezlashtirish uchun octree yoki KD-tree kabi fazoviy ma'lumotlar tuzilmalaridan foydalaning. Bu har bir klaster uchun ko'rib chiqilishi kerak bo'lgan yorug'lik manbalari sonini sezilarli darajada kamaytiradi.
- GPU asosidagi Yorug'likni Taqsimlash: Hisoblash shaderlari (WebGL 2.0+) yordamida yorug'likni taqsimlash jarayonini GPU'ga yuklash ishlash samaradorligini, ayniqsa ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalar uchun sezilarli darajada oshirishi mumkin.
- Bitmask Optimallashtiruvi: Klaster-yorug'lik ko'rinishini bitmasklar yordamida ifodalang. Bu keshning kogerentligini yaxshilashi va xotira o'tkazuvchanligi talablarini kamaytirishi mumkin.
- Shader Optimallashtiruvlari: Ko'rsatmalar va xotiraga kirishlar sonini kamaytirish uchun fragment shaderini optimallashtiring. Yoritish hisob-kitoblari uchun samarali ma'lumotlar tuzilmalari va algoritmlardan foydalaning. Kerakli joylarda tsikllarni oching (unroll).
- Yorug'lik uchun LOD (Detallashtirish Darajasi): Uzoqdagi obyektlar uchun qayta ishlanadigan yorug'lik manbalari sonini kamaytiring. Bunga yoritish hisob-kitoblarini soddalashtirish yoki yorug'likni butunlay o'chirish orqali erishish mumkin.
- Vaqtinchalik Kogerentlik: Oldingi kadrlardagi yorug'lik taqsimotlarini qayta ishlatib, vaqtinchalik kogerentlikdan foydalaning. Faqat sezilarli darajada harakatlangan yorug'lik manbalari uchun taqsimotni yangilang.
- Suzuvchi Nuqtali Aniqlik: Ba'zi yoritish hisob-kitoblari uchun shaderda pastroq aniqlikdagi suzuvchi nuqtali raqamlardan (masalan, `mediump`) foydalanishni ko'rib chiqing, bu ba'zi GPU'larda ishlashni yaxshilashi mumkin.
- Mobil Optimallashtirish: Yorug'lik sonini kamaytirish, shaderlarni soddalashtirish va pastroq o'lchamdagi teksturalardan foydalanish orqali mobil qurilmalar uchun optimallashtiring.
Afzalliklari va Kamchiliklari
Afzalliklari:
- Yaxshilangan Ishlash Samaradorligi: Har bir fragment uchun talab qilinadigan yorug'lik hisob-kitoblari sonini sezilarli darajada kamaytiradi, bu an'anaviy to'g'ridan-to'g'ri renderingga qaraganda yaxshiroq ishlashga olib keladi.
- Kengayuvchanlik: Ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalarga yaxshi moslashadi.
- Moslashuvchanlik: Soya xaritalash va atrof-muhit okklyuziyasi kabi boshqa rendering texnikalari bilan birlashtirilishi mumkin.
Kamchiliklari:
- Murakkablik: An'anaviy to'g'ridan-to'g'ri renderingga qaraganda amalga oshirish murakkabroq.
- Xotira Sarfi: Klaster ma'lumotlari va yorug'lik ro'yxatlarini saqlash uchun qo'shimcha xotira talab qiladi.
- Parametrlarni Sozlash: Optimal ishlashga erishish uchun klaster hajmi va boshqa parametrlarni diqqat bilan sozlashni talab qiladi.
Klasterli Yoritishga Alternativalar
Klasterli Yoritish bir qancha afzalliklarga ega bo'lsa-da, u dinamik yoritishni boshqarishning yagona yechimi emas. Har birining o'ziga xos afzalliklari va kamchiliklari bo'lgan bir nechta muqobil texnikalar mavjud.
- Kechiktirilgan Rendering: Sahna ma'lumotlarini (normalar, chuqurlik va hk.) G-buferlarga render qiling va yoritish hisob-kitoblarini alohida o'tishda bajaring. Ko'p sonli statik yorug'lik manbalari uchun samarali, ammo o'tkazuvchanlikni ko'p talab qilishi va WebGL'da, ayniqsa eski uskunalarda amalga oshirish qiyin bo'lishi mumkin.
- Forward+ Rendering: Klasterli yoritishga o'xshab, yorug'lik to'rini oldindan hisoblash uchun hisoblash shaderidan foydalanadigan to'g'ridan-to'g'ri renderingning bir varianti. Ba'zi uskunalarda kechiktirilgan renderingdan ko'ra samaraliroq bo'lishi mumkin.
- Plitkali Kechiktirilgan Rendering: Ekranni plitkalarga bo'ladi va har bir plitka uchun kechiktirilgan yoritish hisob-kitoblarini bajaradi. An'anaviy kechiktirilgan renderingdan ko'ra samaraliroq bo'lishi mumkin, ayniqsa mobil qurilmalarda.
- Yorug'lik Indeksli Kechiktirilgan Rendering: Plitkali kechiktirilgan renderingga o'xshaydi, lekin yorug'lik ma'lumotlariga samarali kirish uchun yorug'lik indeksidan foydalanadi.
- Oldindan Hisoblangan Nurlanish Transferi (PRT): Statik obyektlar uchun yoritishni oldindan hisoblaydi va natijalarni teksturada saqlaydi. Murakkab yoritishga ega statik sahnalar uchun samarali, ammo dinamik obyektlar bilan yaxshi ishlamaydi.
Global Perspektiva: Platformalar Bo'yicha Moslashuvchanlik
Klasterli yoritishning qo'llanilishi turli platformalar va apparat konfiguratsiyalarida farqlanadi. Zamonaviy ish stoli GPU'lari murakkab klasterli yoritish ilovalarini osongina uddalay olsa-da, mobil qurilmalar va quyi darajadagi tizimlar ko'pincha yanada agressiv optimallashtirish strategiyalarini talab qiladi.
- Ish Stoli GPU'lari: Yuqori xotira o'tkazuvchanligi va ishlov berish quvvatidan foyda oladi, bu esa kattaroq klaster o'lchamlari va murakkabroq shaderlarga imkon beradi.
- Mobil GPU'lar: Cheklangan resurslar tufayli yanada agressiv optimallashtirishni talab qiladi. Kichikroq klaster o'lchamlari, pastroq aniqlikdagi suzuvchi nuqtali raqamlar va soddaroq shaderlar ko'pincha zarur.
- WebGL Mosligi: Tegishli kengaytmalardan foydalanish va faqat WebGL 2.0 da mavjud bo'lgan xususiyatlardan qochish orqali eski WebGL ilovalari bilan moslikni ta'minlang. Eski brauzerlar uchun xususiyatlarni aniqlash va zaxira strategiyalarini ko'rib chiqing.
Qo'llash Holatlariga Misollar
Klasterli yoritish taqsimoti keng ko'lamli ilovalar uchun mos keladi, jumladan:
- O'yinlar: Zarrachalar effektlari, portlashlar va personajlarni yoritish kabi ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalarni render qilish. Marokashdagi yuzlab miltillovchi chiroqlari bo'lgan, har biri dinamik soyalar beradigan gavjum bozorni tasavvur qiling.
- Vizualizatsiyalar: Tibbiy tasvirlash va ilmiy simulyatsiyalar kabi dinamik yoritish effektlariga ega murakkab ma'lumotlar to'plamlarini vizualizatsiya qilish. Murakkab sanoat mashinasi yoki Tokio kabi zich shahar muhiti ichidagi yorug'lik taqsimotini simulyatsiya qilishni ko'rib chiqing.
- Virtual Reallik (VR) va Kengaytirilgan Reallik (AR): Immersiv tajribalar uchun dinamik yoritishli realistik muhitlarni render qilish. Qadimgi Misr maqbarasiga VR-sayohatini, miltillovchi mash'ala yorug'ligi va dinamik soyalar bilan to'ldirilgan holda tasavvur qiling.
- Mahsulot Konfiguratorlari: Foydalanuvchilarga avtomobillar va mebellar kabi mahsulotlarni dinamik yoritish bilan interaktiv tarzda sozlash imkonini berish. Onlaynda maxsus avtomobilni loyihalashtirayotgan foydalanuvchi virtual muhitga asoslangan aniq akslar va soyalarni ko'rishi mumkin.
Amaliy Maslahatlar
WebGL'da klasterli yoritish taqsimotini amalga oshirish va optimallashtirish uchun ba'zi amaliy maslahatlar:
- Oddiy amalga oshirishdan boshlang: Asosiy klasterli yoritish taqsimoti bilan boshlang va zaruratga qarab asta-sekin optimallashtirishlarni qo'shing.
- Kodingizni profiling qiling: Ishlashdagi to'siqlarni aniqlash va optimallashtirish harakatlaringizni eng muhim sohalarga qaratish uchun WebGL profiling vositalaridan foydalaning.
- Turli parametrlar bilan tajriba o'tkazing: Optimal klaster hajmi, yorug'likni yo'qotish algoritmi va shader optimallashtiruvlari muayyan sahna va uskunaga bog'liq. Eng yaxshi konfiguratsiyani topish uchun turli parametrlar bilan tajriba o'tkazing.
- GPU asosidagi yorug'lik taqsimotini ko'rib chiqing: Agar siz WebGL 2.0 ni maqsad qilgan bo'lsangiz, yorug'likni taqsimlash jarayonini GPU'ga yuklash uchun hisoblash shaderlaridan foydalanishni ko'rib chiqing.
- Yangiliklardan xabardor bo'ling: Amalga oshirishingiz imkon qadar samarali bo'lishini ta'minlash uchun eng so'nggi WebGL eng yaxshi amaliyotlari va optimallashtirish usullarini kuzatib boring.
Xulosa
WebGL Klasterli Yoritish Taqsimoti ko'p sonli dinamik yorug'lik manbalari bo'lgan sahnalarni render qilish uchun kuchli va samarali yechim taqdim etadi. Ko'rish frustumini klasterlarga bo'lish va yorug'likni ularning fazoviy joylashuviga qarab klasterlarga taqsimlash orqali ushbu texnika har bir fragment uchun talab qilinadigan yorug'lik hisob-kitoblari sonini sezilarli darajada kamaytiradi, bu esa ishlash samaradorligini oshiradi. Amalga oshirish murakkab bo'lishi mumkin bo'lsa-da, ishlash samaradorligi va kengayuvchanlik nuqtai nazaridan uning afzalliklari uni dinamik yoritish bilan ishlaydigan har qanday WebGL ishlab chiquvchisi uchun qimmatli vositaga aylantiradi. WebGL va GPU apparaturasining uzluksiz rivojlanishi shubhasiz klasterli yoritish texnikalarida yanada katta yutuqlarga olib keladi va yanada realistik va immersiv veb-asosidagi tajribalarni yaratishga imkon beradi.
Muayyan dasturingiz va maqsadli uskunangiz uchun optimal ishlashga erishish uchun kodingizni keng qamrovli profiling qilishni va turli parametrlar bilan tajriba o'tkazishni unutmang.